package service

import (
	"fmt"
	ClickHouse "gin/database"
	"gin/model"
	"gin/types"
	"time"
)

type NeedProject struct {
}

// AssetTotalList 资产统计列表
func (N NeedProject) AssetTotalList(tenantId, userId int64, req types.AssetTotalListReq) (res []types.AssetTotalListRes, err error) {

	var ModuleList []model.Module
	var ModuleMap = make(map[string]*model.Module)
	err = ClickHouse.DB.Model(&model.Module{}).Find(&ModuleList).Error
	for i, v := range ModuleList {
		ModuleMap[v.Code] = &ModuleList[i]
	}

	var statusList []model.Status
	var PublishedStatusIds []int64         // 已发布状态
	PublishedStatusMap := map[string]bool{ // 未开始 待发布  已取消
		"not_started":      true,
		"ready_to_publish": true,
		"closed":           true,
	}
	var statusMap = make(map[string]*model.Status)
	err = ClickHouse.DB.Model(&model.Status{}).Find(&statusList).Error
	for i, v := range statusList {
		statusMap[v.Code] = &statusList[i]
		if !PublishedStatusMap[v.Code] {
			PublishedStatusIds = append(PublishedStatusIds, v.Id)
		}
	}

	type entityListStruct struct {
		GradeSS      int64  `json:"S+"`
		GradeS       int64  `json:"S"`
		GradeA       int64  `json:"A"`
		GradeB       int64  `json:"B"`
		GradeC       int64  `json:"C"`
		FinalNum     int64  `json:"final_num"`     // 完成数量
		TotalNum     int64  `json:"total_num"`     // 总数
		CategoryName string `json:"category_name"` // 类型名称
	}

	var entityList []entityListStruct
	query := ClickHouse.DB.Model(&model.Entity{}).
		Select("simpleJSONExtractString(entity.json, 'design_category') as CategoryName,"+
			"count((simpleJSONExtractString(entity.json, 'design_grade') = 'S+') or null) as GradeSS,"+
			"count((simpleJSONExtractString(entity.json, 'design_grade') = 'S') or null) as GradeS,"+
			"count((simpleJSONExtractString(entity.json, 'design_grade') = 'A') or null) as GradeA,"+
			"count((simpleJSONExtractString(entity.json, 'design_grade') = 'B') or null) as GradeB,"+
			"count((simpleJSONExtractString(entity.json, 'design_grade') = 'C') or null) as GradeC,"+
			"count(JSONExtractInt(entity.json, 'design_status') IN (?) or null) as FinalNum,"+
			"count(entity.id) as TotalNum", PublishedStatusIds).
		Where("entity.module_id = ? ", ModuleMap["design"].Id).
		Where("JSONLength(JSONExtractString(entity.json, 'design_deprecate_data')) = 0").
		Where("entity.tenant_id = ?", tenantId)
	if req.ProjectId > 0 {
		query.Where("entity.project_id = ?", req.ProjectId)
	}
	//if req.TaskName != "" {
	//	query.Where("entity.name LIKE ?", fmt.Sprintf("%s%s%s", "%", req.TaskName, "%"))
	//}
	if req.EntityName != "" {
		query.Where("entity.name LIKE ?", fmt.Sprintf("%s%s%s", "%", req.EntityName, "%"))
	}
	if len(req.AssetStatus) > 0 { // 资产状态
		var AssetStatusIds []int64
		var assetStatusList []model.Status
		err = ClickHouse.DB.Model(&model.Status{}).Where("code in (?)", req.AssetStatus).Find(&assetStatusList).Error
		for _, v := range assetStatusList {
			AssetStatusIds = append(AssetStatusIds, v.Id)
		}
		query.Where("simpleJSONExtractInt(entity.json, 'design_status') IN (?)", AssetStatusIds)
	}
	if len(req.DesignDemandStatus) > 0 { // 资产需求状态
		query.Where("simpleJSONExtractInt(entity.json, 'design_demand_status') IN (?)", req.DesignDemandStatus)
	}
	if len(req.Grade) > 0 { // 等级
		query.Where("simpleJSONExtractString(entity.json, 'design_grade') IN (?)", req.Grade)
	}
	if len(req.DesignCategory) > 0 { // 资产类型
		query.Where("simpleJSONExtractString(entity.json, 'design_category') IN (?)", req.DesignCategory)
	}
	if req.IsRelate == "yes" { // 已关联
		query.Where("simpleJSONExtractString(entity.json, 'design_relate_level') !=''")
	}
	if req.IsRelate == "no" { // 未关联
		query.Where("simpleJSONExtractString(entity.json, 'design_category') = '场景' and simpleJSONExtractString(entity.json, 'design_relate_level') =''")
	}
	//if req.EpisodeId > 0 { // 集
	//	query.Where("task.episode_id = ?", req.EpisodeId)
	//}
	//if len(req.CategoryIdList) > 0 { // 环节
	//	query.Where("task.step_category_id IN (?)", req.CategoryIdList)
	//}
	if req.ProjectId > 0 {
		query.Where("entity.project_id = ?", req.ProjectId)
	}

	if len(req.InitialEpisodeCodeList) == 0 && req.ProjectId > 0 && req.YearMonth > 0 && len(req.CategoryIdList) > 0 {
		episodeCodeList, err := N.getYearMonthEpisodeStepCategoryPlan(req.YearMonth, req.ProjectId, req.CategoryIdList)
		if err != nil || len(episodeCodeList) == 0 {
			return res, err
		}
		req.InitialEpisodeCodeList = make([]types.InitialEpisodeCodeItem, len(episodeCodeList))
		for i, s := range episodeCodeList {
			req.InitialEpisodeCodeList[i].InitialEpisodeCode = s
		}
	}

	// 集 List
	if len(req.InitialEpisodeCodeList) > 0 {

		var EpisodeName []string
		for _, v := range req.InitialEpisodeCodeList {
			EpisodeName = append(EpisodeName, v.InitialEpisodeCode)
		}

		if req.EpisodeType == "episode_use" { // 本集使用

			type EpisodeStruct struct {
				Id   int64  `json:"id"`
				Code string `json:"code"`
			}
			var EpisodeList []EpisodeStruct
			err = ClickHouse.DB.Model(&model.Entity{}).Where("project_id = ? and `code` IN (?) and module_id IN (select id from module where code = 'episode')", req.ProjectId, EpisodeName).Find(&EpisodeList).Error
			var EpisodeMap = make(map[string]int64)
			for _, v := range EpisodeList {
				EpisodeMap[v.Code] = v.Id
			}
			for i, v := range req.InitialEpisodeCodeList {
				req.InitialEpisodeCodeList[i].InitialEpisodeId = EpisodeMap[v.InitialEpisodeCode]
			}
			sql := InitialEpisodeIdSql(req.InitialEpisodeCodeList, "episode_id", "showings_number")
			type RelationEntityStruct struct {
				EntityId int64 `json:"entity_id"`
			}
			var entityIds []int64
			var RelationEntityList []RelationEntityStruct
			err = ClickHouse.DB.Model(&model.EntityEpisodeRelation{}).Where(sql).Find(&RelationEntityList).Error
			for _, v := range RelationEntityList {
				entityIds = append(entityIds, v.EntityId)
			}
			query.Where("entity.id in (?)", entityIds)
		} else {
			sql := InitialEpisodeCodeSql(req.InitialEpisodeCodeList, "initial_episode_code", "showings_number")
			query.Where(sql)
		}
	}

	err = query.Group("CategoryName").Find(&entityList).Error

	var TmpCategoryCodeMap = make(map[string]string, 0)
	TmpCategoryCodeMap["角色"] = "role"
	TmpCategoryCodeMap["场景"] = "scene"
	TmpCategoryCodeMap["道具"] = "prop"
	TmpCategoryCodeMap["关卡"] = "level"

	var CategoryCodeMap = make(map[string]entityListStruct, 0)
	for _, v := range entityList {
		CategoryCodeMap[v.CategoryName] = v
	}
	// 初始统计图
	defaultCode := []string{"角色", "场景", "道具", "关卡"}
	for _, code := range defaultCode {
		res = append(res, types.AssetTotalListRes{
			GradList:     []string{"S+", "S", "A", "B", "C"},
			GradNum:      []int64{CategoryCodeMap[code].GradeSS, CategoryCodeMap[code].GradeS, CategoryCodeMap[code].GradeA, CategoryCodeMap[code].GradeB, CategoryCodeMap[code].GradeC},
			FinalNum:     CategoryCodeMap[code].FinalNum,
			TotalNum:     CategoryCodeMap[code].TotalNum,
			CategoryName: code,
			CategoryCode: TmpCategoryCodeMap[code],
		})
	}
	return
}

type entityListStruct struct {
	TotalShotNum             int64 `json:"total_shot_num"` // 总镜头数
	FinalShotNum             int64 `json:"final_shot_num"` // 完成镜头数
	LiteraryDrama            int64 `json:"literary_drama"` // 文戏
	LiteraryFinal            int64 `json:"literary_final"`
	MartialArts              int64 `json:"martial_arts"` // 武戏
	MartialArtsFinal         int64 `json:"martial_arts_final"`
	SolveShots               int64 `json:"solve_shots"` // 解算镜头
	SolveShotsFinal          int64 `json:"solve_shots_final"`
	SpecialEffectsShots      int64 `json:"special_effects_shots"` // 特效镜头
	SpecialEffectsShotsFinal int64 `json:"special_effects_shots_final"`
}

// ShotTotalList 镜头统计列表
func (N NeedProject) ShotTotalList(tenantId int64, req types.ShotTotalReq) (res []types.ShotTotalListRes, err error) {

	var ModuleList []model.Module
	var ModuleMap = make(map[string]*model.Module)
	err = ClickHouse.DB.Model(&model.Module{}).Find(&ModuleList).Error
	for i, v := range ModuleList {
		ModuleMap[v.Code] = &ModuleList[i]
	}

	var PublishedStatusIds []int64 // 已发布状态
	var statusList []model.Status
	PublishedStatusMap := map[string]bool{ // 未开始 待发布  已取消
		"not_started":      true,
		"ready_to_publish": true,
		"closed":           true,
	}
	err = ClickHouse.DB.Model(&model.Status{}).Find(&statusList).Error
	for _, v := range statusList {
		if !PublishedStatusMap[v.Code] {
			PublishedStatusIds = append(PublishedStatusIds, v.Id)
		}
	}

	var entityList entityListStruct
	query := ClickHouse.DB.Model(&model.Entity{}).
		Select(
			"count(entity.id) as TotalShotNum,count((JSONExtractInt(entity.json, 'shot_status') IN (?)) or null) as FinalShotNum,"+
				"count((simpleJSONExtractString(entity.json, 'shot_perform_form') = '文戏') or null) as LiteraryDrama,"+
				"count((simpleJSONExtractString(entity.json, 'shot_perform_form') = '文戏' and JSONExtractInt(entity.json, 'shot_status') IN (?)) or null) as LiteraryFinal,"+
				"count((simpleJSONExtractString(entity.json, 'shot_perform_form') = '武戏') or null) as MartialArts,"+
				"count((simpleJSONExtractString(entity.json, 'shot_perform_form') = '武戏' and JSONExtractInt(entity.json, 'shot_status') IN  (?)) or null) as MartialArtsFinal,"+
				"count((simpleJSONExtractString(entity.json, 'shot_cloth_solution') <> '不需要解算') or null) as SolveShots,"+
				"count((simpleJSONExtractString(entity.json, 'shot_cloth_solution') <> '不需要解算' and JSONExtractInt(entity.json, 'shot_status') IN (?)) or null) as SolveShotsFinal,"+
				"count((simpleJSONExtractString(entity.json, 'shot_fx') <> '无特效') or null) as SpecialEffectsShots,"+
				"count((simpleJSONExtractString(entity.json, 'shot_fx') <> '无特效' and JSONExtractInt(entity.json, 'shot_status')  IN (?)) or null) as SpecialEffectsShotsFinal",
			PublishedStatusIds, PublishedStatusIds, PublishedStatusIds, PublishedStatusIds, PublishedStatusIds).
		Where("entity.module_id = ? AND entity.tenant_id = ?", ModuleMap["shot"].Id, tenantId)

	if req.ProjectId > 0 {
		query.Where("entity.project_id = ?", req.ProjectId)
	}
	if req.EntityName != "" {
		query.Where("entity.name  LIKE ?", fmt.Sprintf("%s%s%s", "%", req.EntityName, "%"))
	}
	if len(req.ShotStatus) > 0 {
		var statusIds []int64
		var statusList []model.Status
		err = ClickHouse.DB.Model(&model.Status{}).Where("code in (?)", req.ShotStatus).Find(&statusList).Error
		for _, v := range statusList {
			statusIds = append(statusIds, v.Id)
		}
		query.Where("JSONExtractInt(entity.json, 'shot_status') IN (?)", statusIds)
	}

	if len(req.InitialEpisodeCodeList) == 0 && req.ProjectId > 0 && req.YearMonth > 0 && len(req.CategoryIdList) > 0 {
		episodeCodeList, err := N.getYearMonthEpisodeStepCategoryPlan(req.YearMonth, req.ProjectId, req.CategoryIdList)
		if err != nil || len(episodeCodeList) == 0 {
			return res, err
		}
		req.InitialEpisodeCodeList = make([]types.InitialEpisodeCodeItem, len(episodeCodeList))
		for i, s := range episodeCodeList {
			req.InitialEpisodeCodeList[i].InitialEpisodeCode = s
		}
	}

	if len(req.InitialEpisodeCodeList) > 0 {
		sql := InitialEpisodeCodeSql(req.InitialEpisodeCodeList, "initial_episode_code", "showings_number")
		query.Where(sql)
	}
	// 需求状态
	if len(req.StoryboardDemandStatus) > 0 {
		query.Where("JSONExtractInt(entity.json, 'storyboard_demand_status') IN (?)", req.StoryboardDemandStatus)
	}
	//if len(req.CategoryIdList) > 0 {
	//	query.Where("task.step_category_id IN (?)", req.CategoryIdList)
	//}

	err = query.Take(&entityList).Error
	if err != nil {
		return
	}
	res = append(res, types.ShotTotalListRes{
		TotalNum:     entityList.TotalShotNum,
		FinalNum:     entityList.FinalShotNum,
		CategoryName: "总镜头数",
	})
	res = append(res, types.ShotTotalListRes{
		TotalNum:     entityList.LiteraryDrama,
		FinalNum:     entityList.LiteraryFinal,
		CategoryName: "文戏",
	})

	res = append(res, types.ShotTotalListRes{
		TotalNum:     entityList.MartialArts,
		FinalNum:     entityList.MartialArtsFinal,
		CategoryName: "武戏",
	})

	res = append(res, types.ShotTotalListRes{
		TotalNum:     entityList.SolveShots,
		FinalNum:     entityList.SolveShotsFinal,
		CategoryName: "解算镜头",
	})

	res = append(res, types.ShotTotalListRes{
		TotalNum:     entityList.SpecialEffectsShots,
		FinalNum:     entityList.SpecialEffectsShotsFinal,
		CategoryName: "特效镜头",
	})

	return
}

// getYearMonthEpisodeStepCategoryPlan 查询月度剧集环节计划的剧集列表
func (N NeedProject) getYearMonthEpisodeStepCategoryPlan(yearMonth int64, projectId uint64, categoryIdList []int64) (res []string, err error) {

	e := time.Unix(yearMonth, 0).AddDate(0, 1, 0).Add(-1).Unix()
	err = ClickHouse.DB.Model(&model.Plan{}).
		Joins("JOIN task_relation_tag on plan.task_id = task_relation_tag.task_id JOIN entity on entity.id = plan.entity_id").
		Where("plan.project_id = ? and plan.type = 'step_category' and plan.scope = 'single' and plan.end_time between ? and ?", projectId, yearMonth, e).
		Where("task_relation_tag.link_module_code in ('step_category','show_step_category') and task_relation_tag.link_id in ?", categoryIdList).
		Group("entity.code").
		Select("entity.code").
		Pluck("entity.code", &res).Error

	return
}
